const path = require('path')
const { app, protocol, BrowserWindow, ipcMain, globalShortcut, dialog, screen, crashReporter, Menu } = require('electron')
const { exec } = require('child_process');
const { createWindow } = require('./window');
const { webUrl } = require('./config')
const { saveAPPLog, clearHistoryLogs, saveErrorLog } = require('./log');
const { getCloseSetting, closeServes } = require('./request');
const os = require('os');

const runPath = '../../../run.bat';
const exitPathOnlyWeb = '../../../exit.bat';
const exitPathAllServe = '../../../exit0.bat';
const cdsPath = '../../../cds-logs/sys-error/sys-error.log'
const icsPath = '../../../ics-logs/sys-error/sys-error.log'
const helpPath = 'help/index.html'
const readPath = 'ready/index.html'
const additionalData = { myKey: 'myValue' }
const productName = 'CoruiLab'
const isLinux = process.platform === 'linux'
const isWindow = process.platform === 'win32'
const isMac = process.platform === 'darwin'
let win;
let isCreadted = 0;

app.commandLine.appendSwitch("--ignore-certificate-errors", "true");
// Scheme must be registered before the app is ready
protocol.registerSchemesAsPrivileged([
    { scheme: "app", privileges: { secure: true, standard: true } }
]);
crashReporter.start({
    productName: productName,
    companyName: 'CoruiTech',
    submitURL: 'https://www.coruitech.com',  // 上传到服务器的地址
    uploadToServer: false, // 不上传服务器
    ignoreSystemCrashHandler: false, // 不忽略系统自带的崩溃处理，为 true 时表示忽略，崩溃时不会生成崩溃堆栈文件
});
// 关闭菜单
Menu.setApplicationMenu(false);

const gotTheLock = app.requestSingleInstanceLock(additionalData)
if (!gotTheLock) {
    app.quit()
} else {
    // 如果是window系统，运行bat脚本启动服务
    if (isWindow){
        runBatShell(path.join(__dirname, runPath))
    }
    app.on('ready', createReadyWindow);
    clearHistoryLogs();
}


/**
 * 创建加载窗口
 */
function createReadyWindow(){

    const { width, height } = screen.getPrimaryDisplay().workAreaSize
    const filePath = isLinux ? webUrl + '/ready/index.html' : path.join(__dirname, readPath)

    const readyWin = createWindow(filePath, {
        width: Math.ceil(width*0.25),
        height: Math.ceil(height*0.3),
        webPreferences: {
            preload: path.join(__dirname, "preload.js"),
        },
    })

    readyWin.on('ready-to-show', () => {
        saveAPPLog('Start run CoruiLab.')
    })

    ipcMain.on("conn", () => {
		readyWin.close();
		if(isCreadted == 0) {
			isCreadted = 1;
            // 唤起主窗口
			createMainWindow();
		}
	});
		
	ipcMain.on("quit", () => {
		app.quit()
	});
}

/**
 * 创建主窗口
 */
function createMainWindow(){
    win = createWindow(webUrl, {
        webPreferences: {
            preload: path.join(__dirname, 'preload.js'),
        }
    })

    if (isWindow) {
        win.setThumbnailToolTip(productName);
        win.setThumbarButtons([]);
    }
    
    // 如果是 macOS，则可以通过下面的方式设置
	if (isMac) {
        app.dock.setIcon(nativeImage.createFromPath('./build/icons/1024x1024.png'));
    }

    winEvent()
    appEvent()
    ipcMainEvent()
    checkMainProcessMemory()
}
/**
 * 关闭主窗口
 */
async function closeMainWindow(){
    const closeSetting = await getCloseSetting();
    // 退出 勾选了退出软件时退出服务
    if (closeSetting == 1) {
        await closeServes()
        // if (isWindow){
        //     runBatShell(path.join(__dirname, exitPathAllServe))
        // } 
    } else {
        // if (isWindow){
        //     runBatShell(path.join(__dirname, exitPathOnlyWeb))
        // }
    }
}

/**
 * 帮助文档窗口
 */
function helpWindow() {	
    const filePath = isLinux ? webUrl + '/help/index.html' : path.join(__dirname, helpPath)
    createWindow(filePath, {
        title: 'CoruiLab 在线帮助',
        skipTaskbar: true, // 隐藏任务栏
        icon:"icon.ico",
        frame: true,
        webPreferences: {
            nodeIntegration: true
        }
    })
}

/**
 * 日志窗口
 * @param {*} filePath 
 * @param {*} title 
 */
function logWindow(filePath, title) {
    createWindow(path.join(__dirname, filePath), {
        title: title,
        skipTaskbar: true, // 隐藏任务栏
        icon:"icon.ico",
        frame: true,
        webPreferences: {
            nodeIntegration: true
        }
    })
}

// 主窗口事件
function winEvent(){
    win.on('focus', () => {
        globalShortcut.register('F1', () => {
            helpWindow()
        })
        globalShortcut.register('F10', () => {
            logWindow(cdsPath, 'CDS')
        })
        globalShortcut.register('F11', () => {
            logWindow(icsPath, 'ICS')
        })
    })
    win.on('blur', () => {
		globalShortcut.unregisterAll();
	})

    win.on('closed', () => {
        saveAPPLog('Stop run CoruiLab.')
        win = null
    })

    win.webContents.on('unresponsive', async (data) => {
		saveAPPLog(`win:unresponsive: 性能下降提示`, data)
		const { response } = await dialog.showMessageBox({
			title: '应用程序性能下降',
			message: '是否需要重新加载资源提速',
			buttons: ['确定', '取消'],
			cancelId: 1
		})
		if (response === 0) {
			win.webContents.forcefullyCrashRenderer()
			win.webContents.reload()
		}
	})

    // 监听输入
	let zh = false;
	win.webContents.on('before-input-event', (event, input) => {
		if(input.type ==  'keyUp'){
			// console.log(zh)
			// console.log('in:', input.key, input.type, input.code, input.control, input.key.charCodeAt())
			if(['Control','Shift','Alt'].includes(input.key)) {
				zh = true;
				return
			}
			if(!zh && input.key.length == 1 && !input.control && input.key.charCodeAt() >= 65 && input.key.charCodeAt() <= 122){
				if( ![91,92,93,94,95,96].includes(input.key.charCodeAt()) ){
					win.webContents.send('key-down', {
						key: input?.key
					});
					return
				}
			}
			zh = false;
		}
	})
}
// app事件
function appEvent(){
    app.on('activate', () => {
        if (BrowserWindow.getAllWindows().length === 0) createWindow()
    })
    app.on('window-all-closed', () => {
        if (process.platform !== 'darwin') {
            globalShortcut.unregisterAll();
            app.quit()
        }
    })
}
// 主窗口网页交互事件
function ipcMainEvent(){
    ipcMain.on('create-window', (event, url, config) => {
        createWindow("about")
        // 回复消息到渲染进程
        event.reply('reply-from-main', 'Message received by main process');
    });
    ipcMain.handle("select-folder", async () => {
        const res = await dialog.showOpenDialog({
            properties: ['openDirectory']
        })
        if(!res.canceled){
            return res.filePaths[0]
        }
    });
    ipcMain.handle("select-file", async (e, filters) => {
        const res = await dialog.showOpenDialog({
            properties: ['openFile'],
            filters: filters
        })
        if(!res.canceled){
            return res.filePaths
        }
        return []
    });
    ipcMain.handle("get-memory", async () => {
        return await getMemory();
    });
    ipcMain.handle("get-help", async () => {
        helpWindow();
    });
    ipcMain.on("refresh-all", async () => {
        if (win && !win.isDestroyed()) {
            win.webContents.reloadIgnoringCache();
        }
    });	
    ipcMain.on("reloadPage", async () => {
        if (win && !win.isDestroyed()) {
            win.webContents.reload();
        }
    });
    
    // 粘贴板
    ipcMain.on("write-clipboard", async (e, a) => {
        clipboard.writeText(a);
    });
    ipcMain.handle("read-clipboard", async () => {
        return await clipboard.readText();
    });
    
    //最大化
    ipcMain.on("maximize-window", () => {
        win.isMaximized() ? win.restore() : win.maximize();
    });
    // 最小化
    ipcMain.on("minimize-window", () => {
        win.minimize();
    });
    // 关闭窗口
    ipcMain.on("close-window", async () => {
        try{
            await closeMainWindow()
        } catch(e){
            saveErrorLog('退出异常: ', e)
        } finally {
            win.close();
        }
    });
}

// 脚本运行
function runBatShell(path){
    return new Promise((resolve, reject) => {
        exec(path, (error, stdout, stderr) => {
            if (error) {
                reject(`脚本${path}执行的错误: ${error}`);
                return;
            }
            resolve()
        });
    })
}

function getMemory () {
    return process.memoryUsage()
}
// 内存暂用情况记录
async function checkMainProcessMemory(){
    try{
        const systemMemory = process.getSystemMemoryInfo()
        const cpuUsage = await getSystemCpuUsage();
        const memoryData = await win.webContents.executeJavaScript(`
            (function() {
                // 兼容性判断：确保浏览器支持 performance.memory
                if (!window.performance || !window.performance.memory) {
                return null;
                }

                const memory = window.performance.memory;
                // 返回原始数值（主进程侧统一格式化，避免精度丢失）
                return {
                usedJSHeapSize: memory.usedJSHeapSize,
                totalJSHeapSize: memory.totalJSHeapSize,
                jsHeapSizeLimit: memory.jsHeapSizeLimit
                };
            })()
        `);

        const js_total = (memoryData.jsHeapSizeLimit / 1024 / 1024).toFixed(2)
        const js_used = (memoryData.usedJSHeapSize / 1024 / 1024).toFixed(2)
        const sys_total = (systemMemory.total / 1024 / 1024).toFixed(2)
        const sys_free = (systemMemory.free / 1024 / 1024).toFixed(2)

        const data = {
            'JS total': js_total + 'MB',
            'JS used': js_used + 'MB',
            'SYS total': sys_total + 'GB',
            'SYS free': sys_free + 'GB',
            'CPU': cpuUsage + '%',
        };
    
        /**
         * 记录内存是时机：
         * 1、JS内存占用 > 40%
         * 2、或者 系统可用内存 < 20%
         * 3、或者 CPU使用率 > 80%
         */
        // if (js_used / js_total > 0.4 || sys_free / sys_total < 0.2 || cpuUsage > 80){
        //     saveAPPLog('内存', data)
        // }

        saveAPPLog('内存', data)
    } finally {
        setTimeout(checkMainProcessMemory, 1000 * 30)
    }
}

// 计算 CPU 使用率的工具函数（返回系统整体使用率，单位%）
function getSystemCpuUsage() {
    // 第一次采样：获取每个 CPU 核心的时间统计
    const cpusBefore = os.cpus();
    const startIdle = cpusBefore.reduce((sum, cpu) => sum + cpu.times.idle, 0);
    const startTotal = cpusBefore.reduce((sum, cpu) => sum + Object.values(cpu.times).reduce((a, b) => a + b), 0);
  
    // 延迟 100ms 进行第二次采样（采样间隔越短，实时性越高，但性能消耗略增）
    return new Promise((resolve) => {
      setTimeout(() => {
        const cpusAfter = os.cpus();
        const endIdle = cpusAfter.reduce((sum, cpu) => sum + cpu.times.idle, 0);
        const endTotal = cpusAfter.reduce((sum, cpu) => sum + Object.values(cpu.times).reduce((a, b) => a + b), 0);
  
        // 计算差值
        const idleDiff = endIdle - startIdle;
        const totalDiff = endTotal - startTotal;
        // 使用率 = (总时间 - 空闲时间) / 总时间 * 100%
        const usage = ((totalDiff - idleDiff) / totalDiff * 100).toFixed(2);
        resolve(Number(usage));
      }, 100);
    });
  }